queue/qbuf: remove lifetime requirement on QBuffer Similarly to what the previous commit did for some traits, remove the lifetime generic parameter from QBuffer, and make the reference type generic. This will allow us to use either direct references to the providing queue (which guarantees at compile-time that the queue cannot be mutated while a buffer is being prepared), or reference-counter ones like Rc or Arc (which gives us more freedom as for how long we can keep a QBuffer alive, but require runtime-checks on the provided queue before it can be mutated).
diff --git a/lib/src/device/queue.rs b/lib/src/device/queue.rs index 43a2e99..ff7c21a 100644 --- a/lib/src/device/queue.rs +++ b/lib/src/device/queue.rs
@@ -539,7 +539,7 @@ impl<'a, D: Direction, P: PrimitiveBufferHandles> GetBufferByIndex<'a> for Queue<D, BuffersAllocated<P>> { - type Queueable = QBuffer<'a, D, P, P>; + type Queueable = QBuffer<D, P, P, &'a Queue<D, BuffersAllocated<P>>>; // Take buffer `id` in order to prepare it for queueing, provided it is available. fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { @@ -548,7 +548,7 @@ } impl<'a, D: Direction> GetBufferByIndex<'a> for Queue<D, BuffersAllocated<GenericBufferHandles>> { - type Queueable = GenericQBuffer<'a, D>; + type Queueable = GenericQBuffer<D, &'a Self>; fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { let buffer_info = self.try_obtain_buffer(index)?;
diff --git a/lib/src/device/queue/generic.rs b/lib/src/device/queue/generic.rs index 1a222c6..7bfb326 100644 --- a/lib/src/device/queue/generic.rs +++ b/lib/src/device/queue/generic.rs
@@ -2,6 +2,7 @@ device::queue::{ direction::{Capture, Direction, Output}, qbuf::{CaptureQueueable, OutputQueueable, QBuffer, QueueResult}, + BuffersAllocated, Queue, }, memory::DmaBufHandle, }; @@ -9,7 +10,7 @@ memory::MmapHandle, memory::{BufferHandles, MemoryType, UserPtrHandle}, }; -use std::{fmt::Debug, fs::File}; +use std::{fmt::Debug, fs::File, ops::Deref}; /// Supported memory types for `GenericBufferHandles`. /// TODO: This should be renamed to "DynamicBufferHandles", and be constructed @@ -80,38 +81,52 @@ /// A QBuffer that holds either MMAP or UserPtr handles, depending on which /// memory type has been selected for the queue at runtime. -pub enum GenericQBuffer<'a, D: Direction> { - Mmap(QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>), - User(QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>), - DmaBuf(QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>), +pub enum GenericQBuffer< + D: Direction, + Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, +> { + Mmap(QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>), + User(QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>), + DmaBuf(QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>), } -impl<'a, D: Direction> From<QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>> - for GenericQBuffer<'a, D> +impl<D, Q> From<QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>> for GenericQBuffer<D, Q> +where + D: Direction, + Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, { - fn from(qb: QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>) -> Self { + fn from(qb: QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>) -> Self { GenericQBuffer::Mmap(qb) } } -impl<'a, D: Direction> From<QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>> - for GenericQBuffer<'a, D> +impl<D, Q> From<QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>> + for GenericQBuffer<D, Q> +where + D: Direction, + Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, { - fn from(qb: QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>) -> Self { + fn from(qb: QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>) -> Self { GenericQBuffer::User(qb) } } -impl<'a, D: Direction> From<QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>> - for GenericQBuffer<'a, D> +impl<D, Q> From<QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>> + for GenericQBuffer<D, Q> +where + D: Direction, + Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, { - fn from(qb: QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>) -> Self { + fn from(qb: QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>) -> Self { GenericQBuffer::DmaBuf(qb) } } /// Any CAPTURE GenericQBuffer implements CaptureQueueable. -impl CaptureQueueable<GenericBufferHandles> for GenericQBuffer<'_, Capture> { +impl<Q> CaptureQueueable<GenericBufferHandles> for GenericQBuffer<Capture, Q> +where + Q: Deref<Target = Queue<Capture, BuffersAllocated<GenericBufferHandles>>>, +{ fn queue_with_handles( self, handles: GenericBufferHandles, @@ -125,7 +140,10 @@ } /// Any OUTPUT GenericQBuffer implements OutputQueueable. -impl OutputQueueable<GenericBufferHandles> for GenericQBuffer<'_, Output> { +impl<Q> OutputQueueable<GenericBufferHandles> for GenericQBuffer<Output, Q> +where + Q: Deref<Target = Queue<Output, BuffersAllocated<GenericBufferHandles>>>, +{ fn queue_with_handles( self, handles: GenericBufferHandles,
diff --git a/lib/src/device/queue/qbuf.rs b/lib/src/device/queue/qbuf.rs index f313158..6a1ff3d 100644 --- a/lib/src/device/queue/qbuf.rs +++ b/lib/src/device/queue/qbuf.rs
@@ -4,6 +4,7 @@ use crate::ioctl::{self, QBufIoctlError, QBufResult}; use crate::memory::*; use std::convert::Infallible; +use std::ops::Deref; use std::{ fmt::{self, Debug}, os::fd::RawFd, @@ -61,8 +62,13 @@ /// queue or device cannot be changed while it is being used. Contrary to /// DQBuffer which can be freely duplicated and passed around, instances of this /// struct are supposed to be short-lived. -pub struct QBuffer<'a, D: Direction, P: PrimitiveBufferHandles, B: BufferHandles + From<P>> { - queue: &'a Queue<D, BuffersAllocated<B>>, +pub struct QBuffer< + D: Direction, + P: PrimitiveBufferHandles, + B: BufferHandles + From<P>, + Q: Deref<Target = Queue<D, BuffersAllocated<B>>>, +> { + queue: Q, index: usize, num_planes: usize, timestamp: TimeVal, @@ -71,16 +77,14 @@ _p: std::marker::PhantomData<P>, } -impl<'a, D, P, B> QBuffer<'a, D, P, B> +impl<D, P, B, Q> QBuffer<D, P, B, Q> where D: Direction, P: PrimitiveBufferHandles, B: BufferHandles + From<P>, + Q: Deref<Target = Queue<D, BuffersAllocated<B>>>, { - pub(super) fn new( - queue: &'a Queue<D, BuffersAllocated<B>>, - buffer_info: &Arc<BufferInfo<B>>, - ) -> Self { + pub(super) fn new(queue: Q, buffer_info: &Arc<BufferInfo<B>>) -> Self { let buffer = &buffer_info.features; let fuse = BufferStateFuse::new(Arc::downgrade(buffer_info)); @@ -159,11 +163,12 @@ } } -impl<'a, P, B> QBuffer<'a, Output, P, B> +impl<P, B, Q> QBuffer<Output, P, B, Q> where P: PrimitiveBufferHandles, P::HandleType: Mappable, B: BufferHandles + From<P>, + Q: Deref<Target = Queue<Output, BuffersAllocated<B>>>, { pub fn get_plane_mapping(&self, plane: usize) -> Option<ioctl::PlaneMapping> { let buffer_info = self.queue.state.buffer_info.get(self.index)?; @@ -203,10 +208,11 @@ } /// Any CAPTURE QBuffer implements CaptureQueueable. -impl<P, B> CaptureQueueable<B> for QBuffer<'_, Capture, P, B> +impl<P, B, Q> CaptureQueueable<B> for QBuffer<Capture, P, B, Q> where P: PrimitiveBufferHandles, B: BufferHandles + From<P>, + Q: Deref<Target = Queue<Capture, BuffersAllocated<B>>>, { fn queue_with_handles(self, handles: B) -> QueueResult<(), B> { if handles.len() != self.num_expected_planes() { @@ -233,10 +239,11 @@ } /// Any OUTPUT QBuffer implements OutputQueueable. -impl<P, B> OutputQueueable<B> for QBuffer<'_, Output, P, B> +impl<P, B, Q> OutputQueueable<B> for QBuffer<Output, P, B, Q> where P: PrimitiveBufferHandles, B: BufferHandles + From<P>, + Q: Deref<Target = Queue<Output, BuffersAllocated<B>>>, { fn queue_with_handles(self, handles: B, bytes_used: &[usize]) -> QueueResult<(), B> { if handles.len() != self.num_expected_planes() { @@ -280,11 +287,12 @@ /// empty handles. /// Since we don't receive plane handles, we also don't need to return any, so /// the returned error can be simplified. -impl<P, B> QBuffer<'_, Capture, P, B> +impl<P, B, Q> QBuffer<Capture, P, B, Q> where P: PrimitiveBufferHandles + Default, <P::HandleType as PlaneHandle>::Memory: SelfBacked, B: BufferHandles + From<P>, + Q: Deref<Target = Queue<Capture, BuffersAllocated<B>>>, { pub fn queue(self) -> QBufResult<(), Infallible> { let planes: Vec<_> = (0..self.num_expected_planes()) @@ -300,11 +308,12 @@ /// empty handles. /// Since we don't receive plane handles, we also don't need to return any, so /// the returned error can be simplified. -impl<P, B> QBuffer<'_, Output, P, B> +impl<P, B, Q> QBuffer<Output, P, B, Q> where <P::HandleType as PlaneHandle>::Memory: SelfBacked, P: PrimitiveBufferHandles + Default, B: BufferHandles + From<P>, + Q: Deref<Target = Queue<Output, BuffersAllocated<B>>>, { pub fn queue(self, bytes_used: &[usize]) -> QBufResult<(), Infallible> { // TODO make specific error for bytes_used?